package com.yuandian.management.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandian.api.management.entity.ConfBusiness;
import com.yuandian.api.management.entity.ConfStep;
import com.yuandian.bpm.admin.api.feign.RemoteParamService;
import com.yuandian.bpm.common.core.constant.SecurityConstants;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.security.util.SecurityUtils;
import com.yuandian.constant.RedisKey;
import com.yuandian.enums.ResultCodeEnum;
import com.yuandian.exception.ConfigurationDataException;
import com.yuandian.management.mapper.ConfBusinessMapper;
import com.yuandian.management.service.ConfBusinessService;
import com.yuandian.management.service.ConfStepService;
import com.yuandian.management.utils.AESUtil;
import com.yuandian.management.vo.SearchOptionVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务配置表-Service实现
 * @author zfsn
 * @date 2023-3-13
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ConfBusinessServiceImpl extends ServiceImpl<ConfBusinessMapper, ConfBusiness>
		implements ConfBusinessService {

	@Autowired
	private final ConfBusinessMapper confBusinessMapper;

	@Autowired
	private final ConfStepService confStepService;

	@Autowired
	private final RemoteParamService remoteParamService;
	/**
	 * 重写保存方法
	 * @param confBusiness 业务对象
	 * @return boolean
	 */
	@Override
	@Transactional
	public R<String> saveBusiness(ConfBusiness confBusiness){
		// 特殊需求
		if (exceedMaxBusinessConfigLimit()){
			log.error("添加业务数量超过可配置数量，请联系源典工作人员!");
			return R.failed("添加业务数量超过可配置数量，请联系源典工作人员!");
		}

		if(!checkBusiNameDuplicates(confBusiness)){
			try {
				confBusiness.setCreateBy(SecurityUtils.getUser().getName());
			}catch (Exception e){
				log.error(e.getMessage(), e);
				confBusiness.setCreateBy("admin");
			}

			confBusiness.setCreateTime(LocalDateTime.now());
			// 只作为临时占位符
			confBusiness.setBusinessCode(" ");
			if (confBusinessMapper.insert(confBusiness) > 0) {
				// 根据业务id生成业务编码
				String businessCode = "BR-SB-" + String.format("%08d", confBusiness.getId());
				confBusiness.setBusinessCode(businessCode);
				confBusinessMapper.updateById(confBusiness);
				return R.ok();
			}
		} else {
			List<ConfBusiness> list = super.list(new LambdaQueryWrapper<ConfBusiness>()
					.eq(ConfBusiness::getSystemId, confBusiness.getSystemId())
					.eq(ConfBusiness::getName, confBusiness.getName()));
			if (!CollectionUtils.isEmpty(list)){
				confBusiness.setBusinessCode(list.get(0).getBusinessCode());
			}
			log.warn("业务名称：{}存在重复", confBusiness.getName());
			return R.failed(ResultCodeEnum.BUSINESS_NAME_EXIST.getMsg());
		}

		return R.failed(ResultCodeEnum.INSERT_FAIL.getMsg());
	}

	/**
	 * 重写修改方法
	 * @param confBusiness 业务对象
	 * @return boolean
	 */
	@Override
	public R<String> updateBusinessById(ConfBusiness confBusiness){
		if(!checkBusiNameDuplicates(confBusiness)){
			confBusiness.setUpdateBy(SecurityUtils.getUser().getName());
			confBusiness.setUpdateTime(LocalDateTime.now());
			super.updateById(confBusiness);
			return R.ok();
		}
		log.warn("业务名称：{}存在重复", confBusiness.getName());
		return R.failed(ResultCodeEnum.BUSINESS_NAME_EXIST.getMsg());
	}

	/**
	 * 专属指标导入导出功能查询业务
	 *
	 * @param confBusiness 业务vo
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfBusiness> queryToImport(ConfBusiness confBusiness) {
		Page<ConfBusiness> confBusinessPage = listPage(confBusiness);
		if (confBusinessPage.getTotal() > 0) {
			List<ConfBusiness> confBusinesses = confBusinessPage.getRecords();
			List<String> businessCodes = confBusinesses.stream().map(ConfBusiness::getBusinessCode).collect(Collectors.toList());

			//将步骤放入对应的业务对象之中
			List<ConfStep> confStepList = confStepService.list(new LambdaQueryWrapper<ConfStep>().in(ConfStep::getBusinessCode, businessCodes));
			Map<String, List<ConfStep>> confStepMap = confStepList.stream().collect(Collectors.groupingBy(ConfStep::getBusinessCode));

			for (ConfBusiness business : confBusinesses) {
				if (confStepMap.containsKey(business.getBusinessCode())) {
					business.setStepList(confStepMap.get(business.getBusinessCode()));
				}
			}
		}
		return confBusinessPage;
	}

	/**
	 * 通过系统id查询已确认的关键业务列表(远程接口）
	 *
	 * @param systemId 业务vo
	 * @return 通用返回对象
	 */
	@Override
	public List<ConfBusiness> queryKeyBusinessBySystemId(Integer systemId) {
		return confBusinessMapper.queryKeyBusinessBySystemId(systemId);
	}

	/**
	 * 判断业务名称是否重复
	 * @param confBusiness 业务对象
	 */
	private boolean checkBusiNameDuplicates(ConfBusiness confBusiness) {
		return confBusinessMapper.checkBusiNameDuplicates(confBusiness) > 0;
	}

	/**
	 * 判断业务是否被确认
	 *  @param businessIds 业务id
	 * @param isConfirm 是否确认业务
	 * @return boolean
	 */
	@Override
	public boolean confirmBusiness(List<Integer> businessIds, boolean isConfirm) {
		UpdateWrapper<ConfBusiness> updateWrapper = new UpdateWrapper<>();
		updateWrapper.set("is_confirm", isConfirm ? 1 : 0);
		updateWrapper.set("update_by", SecurityUtils.getUser().getName());
		updateWrapper.set("update_time", LocalDateTime.now());
		updateWrapper.in("id", businessIds);
		return super.update(updateWrapper);
	}

	/**
	 * 通过系统id获取改系统下的业务数
	 *
	 * @param systemIds 主键
	 * @return 通用返回对象
	 */
	@Override
	public List<Map<String, Integer>> getBusinessCountBySystemIds(List<Integer> systemIds) {
		return confBusinessMapper.getBusinessCountBySystemIds(systemIds);
	}


	/**
	 * 分页查询
	 *
	 * @param confBusiness 筛选条件
	 * @return 通用返回对象
	 */
    @Override
    public Page<ConfBusiness> listPage(ConfBusiness confBusiness) {
		confBusiness.setPageNum(confBusiness.getPageNum() == null ? 1 : confBusiness.getPageNum());
		confBusiness.setPageSize(confBusiness.getPageSize() == null ? 10 : confBusiness.getPageSize());
		Page<ConfBusiness> page = new Page<>(confBusiness.getPageNum(), confBusiness.getPageSize());

		String orderByColumn = confBusiness.getOrderByColumn() == null ? "id" : confBusiness.getOrderByColumn();
		if ("sequence".equalsIgnoreCase(orderByColumn)) {
			orderByColumn = "id, sequence";
		}

		confBusiness.setOrderByColumn(orderByColumn);

		return confBusinessMapper.listPage(page, confBusiness);
    }

    /**
	 * 批量删除业务配置
	 *
	 * 删除改业务及改业务下所有步骤
	 * @param businessIds 业务id
	 * @return boolean
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeBatchByIds(Collection<?> businessIds) {
		QueryWrapper<ConfBusiness> wrapper = new QueryWrapper<>();
		wrapper.in("id", businessIds);
		List<String> businessCodes = super.list(wrapper).stream().map(ConfBusiness::getBusinessCode).collect(Collectors.toList());
		if (!CollectionUtils.isEmpty(businessCodes)) {
			confStepService.removeStepByBusinessCodes(businessCodes);
		}
		//先删除业务下所有的步骤, 再删除改业务
		return super.removeBatchByIds(businessIds);
	}

	/**
	 * 限制配置系统数量
	 * @return boolean
	 */
	private boolean exceedMaxBusinessConfigLimit(){
		String systemLimitMaxEncryptStr = remoteParamService.getByKey(RedisKey.BUSINESS_MAX, SecurityConstants.FROM_IN).getData();
		if (systemLimitMaxEncryptStr == null) {
			log.error("数据库公共参数表未配置: " + RedisKey.BUSINESS_MAX + "参数");
			throw new ConfigurationDataException("公共参数表未配置" + RedisKey.BUSINESS_MAX + "参数");
		}
		String systemLimitMax = AESUtil.decrypt(systemLimitMaxEncryptStr);
		return super.count() >= Integer.parseInt(systemLimitMax);
	}


	/**
	 * 根据步骤编码查询所诉业务
	 * @param stepCodes 步骤编码列表
	 * @return 通用返回对象
	 */
	public List<String> queryBusinessCodeListByStepCode(List<String> stepCodes) {
		return confBusinessMapper.queryBusinessCodeListByStepCode(stepCodes);
	}

	@Override
	public List<ConfBusiness> queryBySystemCodeAndName(ConfBusiness syBus) {
		return this.list(new LambdaQueryWrapper<ConfBusiness>().eq(ConfBusiness::getSystemId, syBus.getSystemId())
				.eq(ConfBusiness::getName, syBus.getName()));
	}

	/**
	 * 根据系统id查询业务
	 * @param systemId
	 * @return
	 */
	@Override
	public List<SearchOptionVo> queryBusinessBySystemId(Integer systemId){
		return this.baseMapper.queryBusinessBySystemId(systemId);
	}
}
